<?php

namespace App\Kuafu\Mybank\Service;

use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Mybank\Enum\MybankAccountEnum;
use App\Kuafu\Mybank\Model\MybankEntryModel;
use App\Kuafu\Mybank\Model\MybankOrderRecordModel;
use App\Kuafu\Mybank\Model\MybankOrderWithholdRecordModel;
use App\Kuafu\Mybank\Model\MybankOrderWithholdRefundRecordModel;
use App\Kuafu\Mybank\Model\MybankWalletRecordModel;
use App\Kuafu\Pay\Enum\MyBankCashierPayEnum;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Pay\Model\RefundStreamModel;
use App\Kuafu\Pay\Service\PayService;
use App\Remote\Mybank\MybankCashierRemote;
use App\Remote\Mybank\Remote;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;

/**
 * 网商小程序支付
 */
class MybankCashierOrderService
{
    public string $shopId;

    public string $merchantId;

    public string $merchantType;

    public function __construct(string $shopId = '', string $merchantId = '')
    {
        $this->merchantId   = $merchantId;
        $this->shopId       = $shopId;
        $this->merchantType = '';
    }


    /**
     * 创建订单
     * @param int $userId
     * @param int $billAmount
     * @param string $tranId
     * @param int $type
     * @param string $billTitle
     * @param string $billRemark
     * @param array $payeeInfo
     * @return array
     */
    public function createOrder(
        int $userId,
        int $billAmount,
        string $tranId,
        int $type = MybankOrderRecordModel::TYPE_KFOS_ORDER,
        string $billTitle = '',
        string $billRemark = '',
        array $payeeInfo = []
    ): array {

        if (!$this->lockOrder($tranId, $type, 5)) {
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '该订单正在生成中, 请勿重复点击');
        }

        self::setMerchantIdByUserId($userId);

        // 判断原订单号是否存在
        $orderRecord = MybankOrderRecordModel::query()->where('tranId', $tranId)->first();
        if (!empty($orderRecord)) {
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '订单已存在, 请勿重复生成');
        }

        if (empty($payeeInfo)) {
            $payeeInfo = MybankAccountEnum::getKfosOrderAccount();
        }

        $payerInfo = [
            'payerId'   => '',// 付方ID
            'payerType' => MybankOrderWithholdRecordModel::WITHHOLD_MEMBER,// 新增MEMBER类型，针对免入驻支付情况，不限定付方商户
        ];
        $isMerchantId = false;// 付方类型是否为商户 企业商户也走免入驻处理(目前企业商户打开支付宝小程序只能用网商钱包)
        if ($this->merchantType != MybankEntryModel::MERCHANT_TYPE_03 && $this->merchantId && $payeeInfo['payeeId'] != $this->merchantId) {
            $isMerchantId = true;
            $payerInfo    = [
                'payerId'   => $this->merchantId,// 付方ID
                'payerType' => MybankOrderWithholdRecordModel::WITHHOLD_MERCHANT,// 付方类型 商户
            ];
        }

        // 统一支付创单接口
        $createOrderRes = MybankCashierRemote::createOrder(
            $tranId,
            $billAmount,
            MyBankCashierPayEnum::ORDER_TYPE_IMME_SINGLE_PAY,
            $payeeInfo,
            $payerInfo,
            $billTitle,
            $billRemark
        );

        if ($createOrderRes['RespInfo']['ResultCode'] != '0000') {
            Log::channel('mybank')->info('网商小程序支付-createOrderErr', [
                'tranId'         => $tranId,
                'shopId'         => $this->shopId,
                'merchantId'     => $this->merchantId,
                'billAmount'     => $billAmount,
                'payeeInfo'      => $payeeInfo,
                'billTitle'      => $billTitle,
                'billRemark'     => $billRemark,
                'createOrderRes' => $createOrderRes,
            ]);
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '网商小程序支付订单创建失败');
        }

        $orderNo     = $createOrderRes['OrderNo'] ?? '';// 业务交易订单号
        $outTradeNo  = $createOrderRes['OutTradeNo'] ?? '';// 原外部订单请求流水号
        $createOrderRes['oldOrderPayUrl'] = base64_decode($createOrderRes['OrderPayUrl'] ?? '');// 订单支付URL,平台可据此生成二维码(Base64格式，使用前先解码)

        $isvOrgId = Remote::getIsvOrgId();
        if ($isMerchantId) {// 双方入驻支付链接
            $orderPayUrl = "alipays://platformapi/startapp?appId=2021001187624111&nbupdate=syncforce&query=mchId%3D{$this->merchantId}%26order%3D{$orderNo}%26isv%3D{$isvOrgId}%26app%3Dbkclfs%26t%3DPAY";
        } else {// 单边入驻支付链接

            // 支付短链构建 免入驻支付的： alipays://platformapi/startapp?appId=2021001187624111&nbupdate=syncforce&query=order%3D{order}%26isv%3D{ISV_ORG_ID}%26app%3Dbkclfs%26t%3DPAY
            $orderPayUrl = "alipays://platformapi/startapp?appId=2021001187624111&nbupdate=syncforce&query=order%3D{$orderNo}%26isv%3D{$isvOrgId}%26app%3Dbkclfs%26t%3DPAY";
        }

        if (isTest()) {
            $uid      = '2088502337851303';// 支付宝UID
            // 线下免入驻支付链接用这个，替换里面的参数
            $orderPayUrl = "alipays://platformapi/startapp?appId=2021002115660005&nbupdate=syncforce&query=order%3D{$orderNo}%26isv%3D{$isvOrgId}%26app%3Dbkclfs%26t%3DPAY%26uid%3D{$uid}";
        }
        $createOrderRes['newOrderPayUrl'] = $orderPayUrl;

        /**
         * 生成网商账单-mybank_order_record
         */
        $orderRecord = (new MybankOrderRecordModel())->genBillOrder(
            $this->shopId,
            $this->merchantId,
            $billRemark,
            $billAmount,
            $tranId,
            $billTitle,
            $type
        );

        // 创建协议代扣记录
        $withholdModel                 = new MybankOrderWithholdRecordModel();
        $withholdModel->outTradeNo     = $outTradeNo;// 原外部订单请求流水号
        $withholdModel->outOrderNo     = $tranId;// payNo-支付流水号
        $withholdModel->billRecordId   = $orderRecord->orderId;// 网商账单-mybank_order_record-orderId
        $withholdModel->orderNo        = $orderNo;// 网商订单号
        $withholdModel->totalAmount    = $billAmount;// 金额
        $withholdModel->currency       = 'CNY';
        $withholdModel->payerId        = $payerInfo['payerId'];// 付方商户号
        $withholdModel->payerType      = $payerInfo['payerType'];
        $withholdModel->payeeId        = $payeeInfo['payeeId'];// 收方Id
        $withholdModel->payeeType      = $payeeInfo['payeeType'];
        $withholdModel->memo           = '';
        $withholdModel->status         = MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUBMIT;
        $withholdModel->submitDateTime = time();// 交易提交时间
        $withholdModel->save();

        Log::channel('mybank')->info('网商小程序支付-createOrder', [
            'tranId'         => $tranId,
            'shopId'         => $this->shopId,
            'merchantId'     => $this->merchantId,
            'billAmount'     => $billAmount,
            'payeeInfo'      => $payeeInfo,
            'payerInfo'      => $payerInfo,
            'billTitle'      => $billTitle,
            'billRemark'     => $billRemark,
            'createOrderRes' => $createOrderRes,
            'orderRecord'    => $orderRecord,
        ]);

        return BaseService::returnData(BaseCodeEnum::OK, 'success', [
            'tranId'      => $tranId,
            'outTradeNo'  => $outTradeNo,
            'orderNo'     => $orderNo,
            'orderPayUrl' => $orderPayUrl,
        ]);

    }


    /**
     * 查询订单详情
     *
     * @param string $outTradeNo
     * @param string $orderNo
     * @param int $shopId
     * @param string $subject
     * @param bool $isGetStatus
     * @return array
     */
    public function getOrderInfo(
        string $outTradeNo,
        string $orderNo,
        int $shopId,
        string $subject,
        bool $isGetStatus = false
    ): array
    {
        if (!$this->shopId && $shopId) {
            $this->shopId = $shopId;
        }
        $queryRes = MybankCashierRemote::queryOrder($orderNo, $outTradeNo);

        if ($queryRes['RespInfo']['ResultCode'] != '0000') {
            Log::channel('mybank')->info('网商小程序支付-getOrderInfoErr', [
                'outTradeNo' => $outTradeNo,
                'orderNo'    => $orderNo,
                'queryRes'   => $queryRes,
            ]);
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '网商小程序支付订单查询失败');
        }

        Log::channel('mybank')->info('网商小程序支付-getOrderInfo', [
            'outTradeNo' => $outTradeNo,
            'orderNo'    => $orderNo,
            'queryRes'   => $queryRes,
        ]);
        if ($isGetStatus) {// 只查询状态
            return [
                'status' => $queryRes['Status'] == MyBankCashierPayEnum::TRADE_STATUS_OK,
                'msg'    => MyBankCashierPayEnum::TRADE_STATUS_TEXT_MAPPING[$queryRes['Status']] ?? '',
            ];
        }

        $code = BaseCodeEnum::OK;
        $msg  = '付款成功';
        if ($queryRes['Status'] == MyBankCashierPayEnum::TRADE_STATUS_FAIL) {// 订单失败
            $code = $queryRes['ErrorCode'] ?? 500;
            $msg  = '付款失败';
        }

        $returnData = [
            'outTradeNo'               => $queryRes['OutTradeNo'] ?? '',// 外部流水号
            'status'                   => $queryRes['Status'] ?? 0,// // 状态
            'finishDateTime'           => $queryRes['PayTime'] ? strtotime($queryRes['PayTime']) : 0,// 支付完成时间
            'orderType'                => $queryRes['OrderType'] ?? 0,// 订单类型
            'totalAmount'              => $queryRes['TotalAmount'] ?? 0,// 预付金额(金额为分)
            'currency'                 => $queryRes['Currency'] ?? '',// 币种，默认CNY
            'payerId'                  => $queryRes['PayerId'] ?? '',// 付方ID
            'payerType'                => $queryRes['PayerType'] ?? '',// 付方类型
            'payeeId'                  => $queryRes['PayeeId'] ?? '',// 收方ID
            'payeeType'                => $queryRes['PayeeType'] ?? '',// 收方类型
            'subOrderList'             => $queryRes['SubOrderList'] ?? '',// 合并支付时，明细单列表
            'errorCode'                => $queryRes['ErrorCode'] ?? 500,// 错误码
            'errorDesc'                => $queryRes['ErrorDesc'] ?? '',// 错误描述
            'payAssetType'             => $queryRes['PayAssetType'] ?? '',// 支付方式枚举值
            'payToolType'              => $queryRes['PayToolType'] ?? '',// 支付工具类型
            'specifiedPayToolTypeList' => $queryRes['SpecifiedPayToolTypeList'] ?? '',// 指定支付工具类型
            'payerName'                => $queryRes['PayerName'] ?? '',// 付方姓名 商户名称MerchantName
            'payeeCardType'            => $queryRes['PayeeCardType'] ?? '',// 收方卡类型
            'payeeCardName'            => $queryRes['PayeeCardName'] ?? '',// 收方卡名称
            'payeeCardContactLine'     => $queryRes['PayeeCardContactLine'] ?? '',// 收方卡行
            'operateNo'                => $queryRes['OperateNo'] ?? '',// 当前操作交易号
            'actualPayAmount'          => $queryRes['ActualPayAmount'] ?? '',// 实际支付金额
            'payerAgtFeeAmount'        => $queryRes['PayerAgtFeeAmount'] ?? '',// 支付手续费
        ];

        if ($queryRes['Status'] == MyBankCashierPayEnum::TRADE_STATUS_OK) {

            // 更新网商订单记录
            $orderRecord = MybankOrderRecordModel::query()->where('tranId', $outTradeNo)->first();
            if ($orderRecord) {
                $orderRecord->shopId     = $this->shopId ?? 0;
                $orderRecord->payStatus  = MybankOrderRecordModel::PAY_STATUS_PAID;
                $orderRecord->completeAt = $returnData['finishDateTime'];
                $orderRecord->save();
            }

            // 更新网商协议代扣记录表
            $res = MybankOrderWithholdRecordModel::getInfo($outTradeNo);
            if ($res) {
                MybankOrderWithholdRecordModel::updateById($res->id,
                    [
                        'status'         => MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS,
                        'finishDateTime' => time(),// 交易完结时间
                    ]);
            }

            // 支付成功 商户 使用 网商余额支付 需更新钱包余额
            $merchantId           = '';
            $afterRemainingAmount = 0;
            if ($returnData['payerId'] && $returnData['payAssetType'] == MyBankCashierPayEnum::PAY_TYPE_CLOUD_FUNDS_ACCOUNT) {
                $merchantId = $returnData['payerId'];

                // 获取余额
                $balanceInfo          = MybankService::getMerchantBalance($merchantId);
                $balanceFreeze        = $balanceInfo['BALANCE_FREEZE'] ?? 0;
                $balancePAY           = $balanceInfo['PAY'] ?? 0;
                $afterRemainingAmount = (int)bcadd($balanceFreeze, $balancePAY);
            }

            // 钱包添加记录
            MybankOrderWithholdService::walletRecordAdd(
                $merchantId,
                MybankWalletRecordModel::PAY_TRANS_TYPE,
                $returnData['totalAmount'],
                $afterRemainingAmount,
                $this->shopId ?? 0,
                0,
                MybankWalletRecordModel::RECORD_ID_TYPE_CASHIER_PAY,
                MybankWalletRecordModel::PLATFORM_TYPE_MYBANK,
                MybankOrderRecordModel::WALLET_TYPE_SHOW_TYPE_TEXT[$orderRecord->type],
                $orderNo,
                '（网商结算台）',
                $returnData['finishDateTime'],
                MybankWalletRecordModel::SUCCESS_STATUS,
                MybankWalletRecordModel::SHOW_RECORD
            );
        }

        return BaseService::returnData($code, $msg, $returnData);
    }

    /**
     * 支付退回申请接口
     * @param string $orderNo
     * @param string $thirdPayNo
     * @param int $refundAmount
     * @param string $refundReason
     * @return array
     */
    public function refundOrder(string $orderNo, string $thirdPayNo, int $refundAmount, string $refundReason): array
    {
        if (!$this->lockOrder($orderNo . '_' . $thirdPayNo, MyBankCashierPayEnum::REFUND_STATUS_APPLY, 5)) {
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '退款中 请勿重复退款');
        }

        if (empty($refundReason)) {
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '退款理由不能为空');
        }

        if ($refundAmount <= 0) {
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '退款金额不能小于等于 0');
        }

        $mybankOrderWithholdRecordRes = MybankOrderWithholdRecordModel::getInfo($orderNo);// 查询收款方信息
        if ($mybankOrderWithholdRecordRes) {
            $payeeInfo = [
                'payeeId'   => $mybankOrderWithholdRecordRes->payeeId ?? '',// 收方ID
                'payeeType' => $mybankOrderWithholdRecordRes->payeeType ?? '',
            ];
        } else {
            $payeeInfo = MybankAccountEnum::getKfosOrderAccount();
        }

        $refundApplyRes = MybankCashierRemote::refundApplyOrder($orderNo, $thirdPayNo, $refundAmount, $payeeInfo,
            $refundReason, '', '');

        if ($refundApplyRes['RespInfo']['ResultCode'] != '0000') {
            Log::channel('mybank')->info('网商小程序支付-refundOrderErr', [
                'thirdPayNo'     => $thirdPayNo,
                'orderNo'        => $orderNo,
                'refundAmount'   => $refundAmount,
                'refundReason'   => $refundReason,
                'refundApplyRes' => $refundApplyRes,
            ]);
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '支付退回申请接口失败');
        }

        $orderRecord = MybankOrderRecordModel::query()->where('tranId', $orderNo)->first();
        if ($orderRecord) {
            $orderRecord->refundStatus = MybankOrderRecordModel::REFUND_STATUS_REFUNDING;
            $orderRecord->save();
        }

        $returnData = [
            'participantType' => $refundApplyRes['ParticipantType'] ?? '',
            // 退款参与方类型 商户(MERCHANT)、 平台(PLATFORM)
            'participantId'   => $refundApplyRes['ParticipantId'] ?? '',
            // 退款参与方id 如果是商户，则填入merchantId, 如果是平台，则填入isvOrgId
            'relateOrderNo'   => $refundApplyRes['RelateOrderNo'] ?? '',
            // 关联网商订单号
            'refundOrderNo'   => $refundApplyRes['RefundOrderNo'] ?? '',
            // 退款网商订单号
            'outRefundNo'     => $refundApplyRes['OutRefundNo'] ?? '',
            // 退款交易号
        ];

        // 创建退款代扣记录
        $withholdRefundModel                  = new MybankOrderWithholdRefundRecordModel();
        $withholdRefundModel->participantType = $mybankOrderWithholdRecordRes->payeeType ?? '';// 退款付方类型
        $withholdRefundModel->participantId   = $mybankOrderWithholdRecordRes->payeeId ?? '';// 退款付方id
        $withholdRefundModel->relateOrderNo   = $returnData['relateOrderNo'];// 关联网商订单号
        $withholdRefundModel->outOrderNo      = $orderNo;// OutOrderNo
        $withholdRefundModel->outRefundNo     = $thirdPayNo;// 退款外部交易号,由合作方生成
        $withholdRefundModel->refundOrderNo   = $returnData['refundOrderNo'];// 退款外部交易号
        $withholdRefundModel->refundAmount    = $refundAmount;
        $withholdRefundModel->currency        = $mybankOrderWithholdRecordRes->currency ?? '';
        $withholdRefundModel->refundReason    = $refundReason;
        $withholdRefundModel->status          = MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUBMIT;
        $withholdRefundModel->memo            = '';
        $withholdRefundModel->extInfo         = '';
        $withholdRefundModel->submitDateTime  = time();// 交易提交时间
        $withholdRefundModel->save();

        Log::channel('mybank')->info('网商小程序支付-refundOrder', [
            'thirdPayNo'     => $thirdPayNo,
            'orderNo'        => $orderNo,
            'refundApplyRes' => $refundApplyRes,
        ]);
        return BaseService::returnData(BaseCodeEnum::OK, 'success', $returnData);
    }

    /**
     * 支付退回查询接口
     * @param string $orderNo
     * @param string $outTradeNo
     * @param string $refundOrderNo
     * @param int $shopId
     * @param string $subject
     * @return array
     */
    public function getRefundQueryOrder(
        string $orderNo,
        string $outTradeNo,
        string $refundOrderNo,
        int $shopId,
        string $subject
    ): array
    {
        if (!$this->shopId && $shopId) {
            $this->shopId = $shopId;
        }

        $mybankOrderWithholdRecordRes = MybankOrderWithholdRecordModel::getInfo($orderNo);// 查询收款方信息
        if ($mybankOrderWithholdRecordRes) {
            $payeeInfo = [
                'payeeId'   => $mybankOrderWithholdRecordRes->payeeId ?? '',// 收方ID
                'payeeType' => $mybankOrderWithholdRecordRes->payeeType ?? '',
            ];
        } else {
            $payeeInfo = MybankAccountEnum::getKfosOrderAccount();
        }

        $queryRes = MybankCashierRemote::refundQueryOrder($orderNo, $outTradeNo, $refundOrderNo, $payeeInfo);

        if ($queryRes['RespInfo']['ResultCode'] != '0000') {
            Log::channel('mybank')->info('网商小程序支付-getRefundQueryOrderErr', [
                'outTradeNo'     => $outTradeNo,
                'orderNo'        => $orderNo,
                'refundOrderNo'  => $refundOrderNo,
                'refundQueryRes' => $queryRes,
            ]);
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '支付退回查询接口失败');
        }

        $returnData = [
            'participantType'      => $queryRes['ParticipantType'] ?? '',
            // 退款参与方类型 商户(MERCHANT)、 平台(PLATFORM)
            'participantId'        => $queryRes['ParticipantId'] ?? '',
            // 退款参与方id 如果是商户，则填入merchantId, 如果是平台，则填入isvOrgId
            'relateOrderNo'        => $queryRes['RelateOrderNo'] ?? '',
            // 关联网商订单号
            'refundOrderNo'        => $queryRes['RefundOrderNo'] ?? '',
            // 退款网商订单号
            'channelRefundOrderNo' => $queryRes['ChannelRefundOrderNo'] ?? '',
            // 聚合支付渠道退款单号
            'outRefundNo'          => $queryRes['OutRefundNo'] ?? '',
            // 外部退款交易号
            'refundAmount'         => $queryRes['RefundAmount'] ?? 0, // 退款金额。币种同原交易
            'currency'             => $queryRes['Currency'] ?? '',
            // 币种，必须同原交易
            'status'               => $queryRes['Status'] ?? '',
            // 状态(SUCCESS, FAIL,DEALING)
//            'refundAmount'         => $queryRes['ParticipantActualRefundAmount'] ?? 0,
            // 商户实际退款金额
            'refundFinishDate'     => $queryRes['RefundFinishDate'] ? strtotime($queryRes['RefundFinishDate']) : 0,
            // 退款完成时间（成功时出现）
            'errorCode'            => isset($queryRes['ErrorCode']) && !empty($returnData['ErrorCode']) ? $queryRes['ErrorCode'] : 0,
            // 错误码
            'errorDesc'            => isset($queryRes['ErrorDesc']) && !empty($returnData['ErrorDesc']) ? $queryRes['ErrorDesc'] : '',
            // 错误描述
            'extInfo'              => isset($queryRes['ExtInfo']) && !empty($returnData['ExtInfo']) ? $queryRes['ExtInfo'] : '',
            // 扩展信息,Map的json序列化后Base64
            'memo'                 => isset($queryRes['Memo'])&&!empty($returnData['memo'])?$queryRes['Memo']:"",
            // 备注
        ];

        $code = BaseCodeEnum::OK;
        $msg  = '退款成功';

        if ($returnData['status'] == MyBankCashierPayEnum::REFUND_STATUS_FAIL) {
            $code = $returnData['errorCode'] ?? 500;
            $msg  = '退款失败';
        }

        if ($returnData['status'] == MyBankCashierPayEnum::REFUND_STATUS_OK) {

            // 更新网商订单记录
            $orderRecord = MybankOrderRecordModel::query()->where('tranId', $outTradeNo)->first();
            if ($orderRecord && $orderRecord->refundStatus != MybankOrderRecordModel::REFUND_STATUS_REFUNDED) {
                $orderRecord->refundStatus = MybankOrderRecordModel::REFUND_STATUS_REFUNDED;// 已退款
                $orderRecord->save();

                // 更新退款代扣记录
                $res = MybankOrderWithholdRefundRecordModel::getInfo($outTradeNo);
                if ($res) {
                    MybankOrderWithholdRefundRecordModel::updateById($res->id,
                        [
                            'status'           => MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS,
                            'refundFinishDate' => time(),// 交易完结时间
                        ]);
                }

                // 查询关联钱包扣款记录
                $res                  = MybankWalletRecordModel::query()->where('transId', $orderNo)->first();
                $afterRemainingAmount = 0;
                $merchantId           = '';
                if ($res && $res->merchantId) {// 退款成功 商户 使用 网商余额支付 需更新钱包余额记录

                    // 获取余额
                    $balanceInfo          = MybankService::getMerchantBalance($res->merchantId);
                    $balanceFreeze        = $balanceInfo['BALANCE_FREEZE'] ?? 0;
                    $balancePAY           = $balanceInfo['PAY'] ?? 0;
                    $afterRemainingAmount = (int)bcadd($balanceFreeze, $balancePAY);
                    $merchantId           = $res->merchantId;
                }
                // 钱包添加记录
                MybankOrderWithholdService::walletRecordAdd(
                    $merchantId,
                    MybankWalletRecordModel::EARNING_TRANS_TYPE,
                    $returnData['refundAmount'],
                    $afterRemainingAmount,
                    $this->shopId ?? 0,
                    0,
                    MybankWalletRecordModel::RECORD_ID_TYPE_CASHIER_PAY,
                    MybankWalletRecordModel::PLATFORM_TYPE_MYBANK,
                    MybankOrderRecordModel::WALLET_TYPE_SHOW_TYPE_TEXT[$orderRecord->type],
                    $returnData['refundOrderNo'],
                    '（网商结算台）',
                    $returnData['refundFinishDate'],
                    MybankWalletRecordModel::SUCCESS_STATUS,
                    MybankWalletRecordModel::SHOW_RECORD
                );
            }
        }

        Log::channel('mybank')->info('网商小程序支付-getRefundQueryOrder', [
            'outTradeNo'     => $outTradeNo,
            'orderNo'        => $orderNo,
            'refundQueryRes' => $queryRes,
        ]);
        return BaseService::returnData($code, $msg, $returnData);
    }


    /**
     * 网商小程序支付-统一支付结果通知
     * @param array $requestBody
     * @return array
     */
    public static function unifiedOrderNotify(array $requestBody): array
    {
        Log::channel('mybank')->info('网商小程序支付-统一支付结果通知接口start', [
            'requestBody' => $requestBody,
        ]);

        if (!$requestBody) {
            return [ResponseAlias::HTTP_OK, []];
        }

        $data = [
            'isvOrgId'     => $requestBody['IsvOrgId'] ?? "", //合作方机构号（网商银行分配）
            'orderType'    => $requestBody['OrderType'] ?? '', //订单类型
            'orderNo'      => $requestBody['OrderNo'] ?? '', //网商订单号
            'outTradeNo'   => $requestBody['OutTradeNo'] ?? '', //外部流水号
            'payerId'      => $requestBody['PayerId'] ?? '', //付方ID 商户号MerchantId
            'payerType'    => $requestBody['IsvOrgId'] ?? '', //付方类型 商户MERCHANT
            'payerName'    => $requestBody['PayerName'] ?? '', //付方姓名 商户名称MerchantName
            'payTime'      => $requestBody['PayTime'] ?? '', //支付时间
            'payeeId'      => $requestBody['PayeeId'] ?? '', //收方ID 商户号MerchantId
            'payeeType'    => $requestBody['PayeeType'] ?? '', //收方类型 商户MERCHANT
            'totalAmount'  => $requestBody['TotalAmount'] ?? 0, //支付金额(金额为分)
            'currency'     => $requestBody['Currency'] ?? '', //币种，默认CNY
            'status'       => $requestBody['Status'] ?? '', //状态(SUCCESS, FAIL)
            'errorCode'    => $requestBody['ErrorCode'] ?? '', //错误码
            'errorDesc'    => $requestBody['ErrorDesc'] ?? '', //错误描述
            'payAssetType' => $requestBody['PayAssetType'] ?? '', //支付方式枚举值
        ];

        $payStream = PayStreamModel::suffix(null)->where('payNo', $data['outTradeNo'])->first();
        if ($payStream) {
            // 未支付
            if ($payStream->payStatus == PayStreamModel::PAY_STATUS_0) {
                list($result, $payStatus) = PayService::sPayPolling($payStream);

                Log::channel('mybank')->info('网商小程序支付-统一支付结果通知接口更新支付状态', [
                    'requestBody' => $requestBody,
                    'result'      => $result,
                    'payStatus'   => $payStatus,
                    'payNo'       => $data['outTradeNo'],
                ]);
            }
        }

        Log::channel('mybank')->info('网商小程序支付-统一支付结果通知接口end', [
            'requestBody' => $requestBody,
        ]);
        return [ResponseAlias::HTTP_OK, []];
    }

    /**
     * 网商小程序支付-支付退回通知接口 退款操作已在 支付退回查询接口-getRefundQueryOrder 处理
     * @param array $requestBody
     * @param PayStreamModel $payStream
     * @return array
     */
    public static function refundOrderNotify(array $requestBody, PayStreamModel $payStream): array
    {
        Log::channel('mybank')->info('网商小程序支付-支付退回通知接口start', [
            'requestBody' => $requestBody,
        ]);

        if (!$requestBody) {
            return [ResponseAlias::HTTP_OK, []];
        }

        $data = [
            'isvOrgId'                      => $requestBody['IsvOrgId'] ?? '',
            //合作方机构号（网商银行分配）
            'participantType'               => $requestBody['ParticipantType'] ?? '',
            //退款参与方类型 商户(MERCHANT)、 平台(PLATFORM)
            'participantId'                 => $requestBody['ParticipantId'] ?? '',
            //退款参与方id 如果是商户，则填入merchantId,如果是平台，则填入isvOrgId
            'relateOrderNo'                 => $requestBody['RelateOrderNo'] ?? '',
            //关联网商订单号
            'relateTransNo'                 => $requestBody['RelateTransNo'] ?? '',
            //关联网商支付流水号
            'refundOrderNo'                 => $requestBody['RefundOrderNo'] ?? '',
            //退款网商订单号
            'channelRefundOrderNo'          => $requestBody['ChannelRefundOrderNo'] ?? '',
            //渠道退款单号（聚合 ）
            'outRefundNo'                   => $requestBody['OutRefundNo'] ?? '',
            //退款交易号
            'refundAmount'                  => $requestBody['RefundAmount'] ?? '',
            //退款金额。币种同原交易
            'currency'                      => $requestBody['Currency'] ?? '',
            //币种，必须同原交易
            'status'                        => $requestBody['Status'] ?? 0,
            //状态(SUCCESS, FAIL)
            'participantActualRefundAmount' => $requestBody['ParticipantActualRefundAmount'] ?? '',
            //商户实际退款金额	Number
            'refundFinishDate'              => $requestBody['RefundFinishDate'] ?? '',
            //退款完成时间（成功时出现）
            'errorCode'                     => $requestBody['ErrorCode'] ?? '',
            //错误码
            'errorDesc'                     => $requestBody['ErrorDesc'] ?? '',
            //错误描述
            'extInfo'                       => $requestBody['ExtInfo'] ?? '',
            //扩展信息,Map的json序列化后Base64
            'memo'                          => $requestBody['Memo'] ?? '',
            //备注
        ];

        Log::channel('mybank')->info('网商小程序支付-支付退回通知接口end', [
            'requestBody' => $requestBody,
        ]);
        return [ResponseAlias::HTTP_OK, []];
    }


    /**
     * 通过 UserId 获取网商商户号
     *
     * @param int $userId
     * @return $this
     */
    public function setMerchantIdByUserId(int $userId): self
    {
        $entryList = MybankEntryModel::getEntryIdByMobile($userId, 0, MybankEntryModel::STATUS_3);
        if ($entryList) {
            $info               = collect($entryList)->first();
            $this->merchantId   = $info['merchantId'] ?? '';
            $this->merchantType = $info['merchantType'] ?? '';// 商户类型
        }

        return $this;
    }

    /**
     * 返回锁
     *
     * @param string $id
     * @param string $type
     * @return string
     */
    private function getOrderLockKey(string $id, string $type): string
    {
        return sprintf('mybank_cashier_order:lock:%s:%s', $type, $id);
    }

    /**
     * 网商场景上锁 返回 是否成功上锁
     *
     * @param string $tranId
     * @param string $type
     * @param int $time
     * @return mixed
     */
    public function lockOrder(string $tranId, string $type, int $time)
    {
        $key = $this->getOrderLockKey($type, $tranId);
        $set = Redis::setNx($key, 'locked');

        if ($set) {
            Redis::expire($key, $time);
        }

        return $set;
    }


    /**
     * 通过三方 支付流水号 查询 我方 唯一支付流水号
     * @param array $thirdPayNos
     * @return array
     */
    public static function getKfPayInfoByNos(array $thirdPayNos): array
    {
        return PayStreamModel::suffix(null)
                             ->whereIn('thirdPayNo', $thirdPayNos)
                             ->select(['thirdPayNo', 'payNo', 'bizId'])
                             ->get()
                             ->keyBy('thirdPayNo')->toArray();
    }


    /**
     * 通过三方 唯一退款流水号 查询 三方 支付流水号
     * @param array $thirdRefundNos
     * @return array
     */
    public static function getKfPayRefundInfoByNos(array $thirdRefundNos): array
    {
        return RefundStreamModel::query()
                                ->join('pay_stream', 'pay_stream.payNo', '=', 'refund_stream.payNo')
                                ->whereIn('refund_stream.thirdRefundNo', $thirdRefundNos)
                                ->select(['refund_stream.thirdRefundNo', 'refund_stream.refundNo', 'pay_stream.thirdPayNo'])
                                ->get()
                                ->keyBy('thirdRefundNo')->toArray();
    }


    /**
     * 订单关闭接口
     *
     * @param string $outTradeNo
     * @param string $orderNo
     * @return array
     */
    public function closeOrder(string $outTradeNo, string $orderNo): array
    {
        $mybankOrderWithholdRecordRes = MybankOrderWithholdRecordModel::getInfo($orderNo);// 查询收款方信息
        if ($mybankOrderWithholdRecordRes) {
            $payeeInfo = [
                'payeeId'   => $mybankOrderWithholdRecordRes->payeeId ?? '',// 收方ID
                'payeeType' => $mybankOrderWithholdRecordRes->payeeType ?? '',
            ];
        } else {
            $payeeInfo = MybankAccountEnum::getKfosOrderAccount();
        }

        $res       = MybankCashierRemote::closeOrder($orderNo, $outTradeNo, $payeeInfo);

        if ($res['RespInfo']['ResultCode'] != '0000') {
            Log::channel('mybank')->info('网商小程序支付-closeOrderErr', [
                'outTradeNo' => $outTradeNo,
                'orderNo'    => $orderNo,
                'res'        => $res,
            ]);
            return BaseService::returnData(BaseCodeEnum::ERR_400000, '网商小程序订单关闭接口失败');
        }

        Log::channel('mybank')->info('网商小程序支付-closeOrder', [
            'outTradeNo' => $outTradeNo,
            'orderNo'    => $orderNo,
            'res'        => $res,
        ]);

        $returnData = [
            'outTradeNo' => $res['OutTradeNo'] ?? '',// 外部流水号
            'orderNo'    => $res['OrderNo'] ?? '',// 原网商订单号
        ];

        return BaseService::returnData(BaseCodeEnum::OK, 'success', $returnData);
    }
}
